import datetime

from celery.exceptions import MaxRetriesExceededError
from django.db import transaction
from django.db.models import F

import settings
from social.account.models import User
from social.exceptions import CodeException
from social.im.tasks import send_system_text_message
from social.utils.celery_app import app
from social.utils.face_auth import LivenessFaceVerify, CompareFaceVerify
from social.utils.jpush import JPush
from social.utils.shortcut import get_object_or_none


@app.task()
def add_user_visit(from_user_id, to_user_id):
    from social.user.models import UserVisit
    with transaction.atomic():
        user_visit, created = UserVisit.objects.get_or_create(from_user_id=from_user_id, to_user_id=to_user_id)
        now = datetime.datetime.now().timestamp()
        if created or now - user_visit.updated_at.timestamp() > 180:
            send_visit_message.delay(user_visit.id)
        user_visit.times = F('times') + 1
        user_visit.updated_at = datetime.datetime.now()
        user_visit.save(update_fields=['times', 'updated_at'])


@app.task()
def send_visit_message(visit_id):
    from social.user.models import UserVisit
    user_visit = UserVisit.objects.select_related('from_user', 'to_user').get(id=visit_id)
    to_user = user_visit.to_user
    from social.user.models import UserMsgSetting
    msg_setting, _ = UserMsgSetting.objects.get_or_create(user=to_user)
    if msg_setting.new_visited:
        ids = [user_visit.to_user.hid]
        extra = {
            'link': f'{settings.APP_NAME}://visitor',
            'title': '',
            'content': ''
        }
        content = f'{user_visit.from_user.nickname}访问了你'
        JPush.send_push(ids, settings.APP_TITLE, content, alert=content, content_type='new_visit', extra=extra,
                        channel_id='new_visitor')


@app.task()
def update_user_follow_count(user_id):
    from social.user.models import UserLike
    user = User.objects.get(id=user_id)
    user.follow_count = UserLike.objects.filter(from_user_id=user_id).count()
    user.save(update_fields=['follow_count'])


@app.task()
def update_user_fans_count(user_id):
    from social.user.models import UserLike
    user = User.objects.get(id=user_id)
    user.fans_count = UserLike.objects.filter(to_user_id=user_id).count()
    user.save(update_fields=['fans_count'])


@app.task()
def update_user_friend_count(user_id):
    user = User.objects.get(id=user_id)
    from social.user.models import UserLike
    user.friend_count = UserLike.objects.filter(from_user_id=user_id, is_friend=True).count()
    user.save(update_fields=['friend_count'])


@app.task()
def check_user_avatar(user_id):
    user = User.objects.get(id=user_id)
    try:
        if user.avatar:
            r = LivenessFaceVerify.check_face(user.avatar.url)
            code = int(r['code'])
            if r['code'] == 0:
                r = r['result']
                livemapscore = float(r['liveness']['livemapscore'])
                face_type = r['face_type']['type']
                if livemapscore > 0.3 and face_type == 'human':
                    user.update_avatar_real(True)
                    if user.avatar_auth:
                        face_compare_again.delay(user_id)
                else:
                    user.update_avatar_real(False)
                    if user.avatar_auth:
                        user.update_avatar_auth(False)
                        send_system_text_message.delay(user.im_id, '您上传的用户头像与真人认证头像不是同一人，您的真人认证已失效')
            elif code in [1, 2, 3]:
                # 没有人脸，
                user.update_avatar_real(False)
                if user.avatar_auth:
                    user.update_avatar_auth(False)
                    face_compare_again.delay(user_id)
            elif code in [4, 5, 413]:
                raise CodeException(status_code=code, msg='business error')
    except MaxRetriesExceededError:
        user.update_avatar_real(False)
    except CodeException as e:
        raise check_user_avatar.retry(exc=e, countdown=3, max_retries=5)


@app.task()
def face_compare_again(user_id):
    from social.user.models import UserAuth
    user = User.objects.get(id=user_id)
    if not user.avatar_auth:
        return
    user_auth = UserAuth.objects.get(user_id=user_id)
    try:
        res = CompareFaceVerify.compare(user.avatar.url, user_auth.picture_url)
        if res and res.status_code == 200:
            body = res.body
            if body.code == '200' and float(body.result_object.verify_score) > 60:
                pass
            else:
                # 认证不是同一人
                user.update_avatar_auth(False)
                send_system_text_message.delay(user.im_id, '您上传的用户头像与真人认证头像不是同一人，您的真人认证已失效')
        else:
            raise CodeException(msg='business error')
    except MaxRetriesExceededError:
        user.update_avatar_auth(False)
        send_system_text_message.delay(user.im_id, '您上传的用户头像与真人认证头像不是同一人，您的真人认证已失效')
    except CodeException as e:
        raise face_compare_again.retry(exc=e, countdown=3, max_retries=5)


@app.task()
def send_new_fans_message(user_like_id):
    from social.user.models import UserLike
    user_like = UserLike.objects.select_related('from_user', 'to_user').get(id=user_like_id)
    from social.user.models import UserMsgSetting
    msg_setting, _ = UserMsgSetting.objects.get_or_create(user=user_like.to_user)
    if msg_setting.new_fans:
        ids = [user_like.to_user.hid]
        extra = {
            'link': f'{settings.APP_NAME}://fans',
            'title': '',
            'content': ''
        }
        content = f'{user_like.from_user.nickname}关注了你'
        JPush.send_push(ids, settings.APP_TITLE, content, alert=content, content_type='new_fans', extra=extra,
                        channel_id='new_fans')
